package com.example.lx.myapplication.customView;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.icu.util.TimeZone;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.example.lx.myapplication.R;

/**
 * Created by lx on 2017/6/20.
 */

public class AnalogClock extends View {
    //用来存放三张图片资源
    private Drawable mDial;
    private Drawable mHourHand;
    private Drawable mMinuteHand;
    private Time mCalendar;    //用来记录当前时间

    //用来记录表盘图片的宽和高，
    //以便帮助我们在onMeasure中确定View的大
    //小，毕竟，我们的View中最大的一个Drawable就是它了。
    private int mDialWidth;
    private int mDialHeight;
    //用来跟踪我们的View 的尺寸的变化，
//当发生尺寸变化时，我们在绘制自己
//时要进行适当的缩放。
    private boolean mChanged;
    //用来记录View是否被加入到了Window中，我们在View attached到
//Window时注册监听器，监听时间的变更，并根据时间的变更，改变自己
//的绘制，在View从Window中剥离时，解除注册，因为我们不需要再监听
//时间变更了，没人能看得到我们的View了。
    private boolean mAttached;

    //看名字
    private float mMinutes;
    private float mHour;
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public AnalogClock(Context context) {
        this(context,null);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public AnalogClock(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public AnalogClock(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr,0);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public AnalogClock(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        final Resources r=context.getResources();
        if(mDial==null){
            mDial=context.getDrawable(R.drawable.clock_dial);
        }
         if(mHourHand==null){
             mHourHand=context.getDrawable(R.drawable.clock_hand_hour);
         }
         if(mMinuteHand==null){
             mMinuteHand=context.getDrawable(R.drawable.clock_hand_minute);
         }
            mCalendar=new Time();
           mDialWidth=mDial.getIntrinsicWidth();
        mDialHeight=mDial.getIntrinsicHeight();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.e("AnalogClock","onMeasure");
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);

        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);

        float hScale =1.0f;
        float wScale=1.0f;

        if(widthMode!=MeasureSpec.UNSPECIFIED && widthSize<mDialWidth){
            hScale=(float) widthSize/(float) mDialWidth;
        }
        if(heightMode!=MeasureSpec.UNSPECIFIED && heightSize<mDialHeight){
            wScale=(float)heightSize/(float)mDialHeight;
        }
        float scale=Math.min(hScale,wScale);
        setMeasuredDimension(resolveSizeAndState((int)(mDialWidth*scale),widthMeasureSpec,0),
                resolveSizeAndState((int)(mDialHeight*scale),heightMeasureSpec,0));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Log.e("AnalogClock","onSizeChanged");
        mChanged=true;
    }
   private void onTimeChanged(){
    //   Log.e("AnalogClock","onTimeChanged");
       mCalendar.setToNow();
       int hour =mCalendar.hour;
       int minute =mCalendar.minute;
       int second =mCalendar.second;
        /*这里我们为什么不直接把minute设置给mMinutes，而是要加上
            second /60.0f呢，这个值不是应该一直为0吗？
            这里又涉及到Calendar的 一个知识点，
            也就是它可以是Linient模式，
            此模式下，second和minute是可能超过60和24的，具体这里就不展开了，
            如果不是很清楚，建议看看Google的官方文档中讲Calendar的部分*/
          mMinutes=minute+ second/60.0f;
          mHour=hour+mMinutes/60.0f;
          mChanged=true;

   }
   private final BroadcastReceiver mIntentReceiver =new BroadcastReceiver() {
       @RequiresApi(api = Build.VERSION_CODES.N)
       @Override
       public void onReceive(Context context, Intent intent) {
           //这个if判断主要是用来在时区发生变化时，更新mCalendar的时区的，这
           //样，我们的自定义View在全球都可以使用了。
           if(intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)){
             String tz =intent.getStringExtra("time-zone");
               mCalendar=new Time(TimeZone.getTimeZone(tz).getID());
           }
           //进行时间的更新
           onTimeChanged();
           //invalidate当然是用来引发重绘了。
           invalidate();
       }
   };

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.e("AnalogClock","onAttachedToWindow");
        if(!mAttached){
            mAttached=true;
            IntentFilter filter =new IntentFilter();
            filter.addAction(Intent.ACTION_TIME_TICK);
            filter.addAction(Intent.ACTION_TIME_CHANGED);
            filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
            getContext().registerReceiver(mIntentReceiver,filter);
        }
        mCalendar=new Time();
        onTimeChanged();

    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.e("AnalogClock","onDetachedFromWindow");
        if(mAttached){
            getContext().unregisterReceiver(mIntentReceiver);
            mAttached=false;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e("AnalogClock","onDraw");
        boolean changed =mChanged;
        if(changed){
            mChanged=false;
        }
        int availableWidth=super.getRight()-super.getLeft();
        int availableHeight=super.getBottom()-super.getTop();
        int x =availableWidth/2;
        int y =availableHeight/2;
        final  Drawable dial =mDial;
        int w =dial.getIntrinsicWidth() ;
        int h =dial.getIntrinsicHeight();
        boolean scaled=false;
        if(availableWidth<w || availableHeight<h){
            scaled=true;
            float scale =Math.min((float)availableWidth/(float)w,
                    (float)availableHeight/(float)h);
            canvas.save();
            canvas.scale(scale,scale,x,y);
        }
        if(changed){
            dial.setBounds(x-(w/2),y-(h/2),x+(w/2),y+(h/2));
        }
        dial.draw(canvas);
        canvas.save();
        canvas.rotate(mHour/12.0f*360.0f,x,y);
        final  Drawable hourHand =mHourHand;
        if(changed){
            w=hourHand.getIntrinsicWidth();
            h=hourHand.getIntrinsicHeight();
            hourHand.setBounds(x-(w/2),y-(h/2),x+(w/2),y+(h/2));
        }
         hourHand.draw(canvas);
        canvas.restore();
        canvas.save();
        canvas.rotate(mMinutes/60.0f*360.0f,x,y);
        final Drawable minuteHand =mMinuteHand;
        if(changed){
            w=minuteHand.getIntrinsicWidth();
            h=minuteHand.getIntrinsicHeight();
            minuteHand.setBounds(x-(w/2),y-(h/2),x+(w/2),y+(h/2));
        }
        minuteHand.draw(canvas);
        canvas.restore();
        //最后，我们把缩放的坐标系复原
        if(scaled){
            canvas.restore();
        }

    }
}
